﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using NUnit.Framework;
using Rhino.Mocks;
using XcoAppSpaces.Contracts.Communication;
using XcoAppSpaces.Contracts.Messaging;
using XcoAppSpaces.Contracts.Worker;
using XcoAppSpaces.Core.Communication.WorkerResolve;
using Rhino.Mocks.Constraints;
using System.Threading;
using XcoAppSpaces.Core.Communication;
using XcoAppSpaces.Contracts.Security;

namespace test.XcoAppSpaces.Core.Communication
{
	/*[TestFixture]
	public class ResolveWorkerTest
	{
		private MockRepository mocks = null;
		private IXcoWorkerRegistry workerRegistryMock = null;
		private Port<MessageToSend> messagingPortMock = null;
		private IXcoSecurityService securityServiceMock = null;
		
		private Dispatcher d = null;
		private DispatcherQueue dpq = null;
		private string spaceaddress = null;

		private PortSet<int, string> testWorker = null;
		private Type testWorkerType = null;
		private string testWorkerName = null;
		private Guid testSession;
		
		private ResolveRequest req = null;
		private ResolveWorker resolveWorker = null;
		private ResolveStatus statusToResolve;

		[SetUp]
		public void SetUp()
		{
			mocks = new MockRepository();
			workerRegistryMock = mocks.StrictMock<IXcoWorkerRegistry>();
			messagingPortMock = mocks.StrictMock<Port<MessageToSend>>();
			securityServiceMock = mocks.StrictMock<IXcoSecurityService>();
			d = new Dispatcher();
			dpq = new DispatcherQueue("dpq", d);
			spaceaddress = "testaddress";
			testWorker = new PortSet<int, string>();
			testWorkerType = testWorker.GetType();
			testWorkerName = "testworker";
			testSession = Guid.NewGuid();
		}

		[TearDown]
		public void TearDown()
		{
			mocks.VerifyAll();
			d.Dispose();
		}

		[Test]
		public void ResolveExistingWorker()
		{
			TestResolve(ResolveStatus.Ok);
		}

		[Test]
		public void ResolveNotExistingWorker()
		{
			TestResolve(ResolveStatus.WorkerNotFound);
		}

		[Test]
		public void ResolveWithNoResponse()
		{
			//hangs until timeout because no response is posted! (therefore test takes longer)
			TestResolve(ResolveStatus.NoResponse);
		}

		private void TestResolve(ResolveStatus status)
		{
			//expectations on mocks
			Expect.Call(securityServiceMock.GetClientCredentials(null, spaceaddress)).Return(null);
			messagingPortMock.Post(null);
			LastCall.IgnoreArguments().Constraints(Is.Matching<MessageToSend>(
				m => m.RemoteAddress == spaceaddress &&
					((WorkerMessage)m.Data).WorkerName == null &&
					((WorkerMessage)m.Data).WorkerType == typeof(ResolveWorker) &&
					((WorkerMessage)m.Data).Msg is ResolveRequest &&
					(req = (ResolveRequest)((WorkerMessage)m.Data).Msg).WorkerAddress == spaceaddress && //locally store the request for later access
					req.WorkerName == testWorkerName &&
					req.WorkerType == testWorkerType));
			
			//run test
			mocks.ReplayAll();
			resolveWorker = new ResolveWorker(workerRegistryMock, securityServiceMock, messagingPortMock, dpq);
			statusToResolve = status; //set the status that should be reported back as answer to the given request
			if (status != ResolveStatus.NoResponse) //if "no response" should be tested, don't create a response
			{
				(new Thread(RespondToRequest)).Start();
			}
			ResolveResponse response = resolveWorker.Resolve(spaceaddress, testWorkerType, testWorkerName, null, null);
			Assert.AreEqual(status, (response != null ? response.Status : ResolveStatus.NoResponse));
		}

		private void RespondToRequest()
		{
			Thread.Sleep(100); //wait a short time for request
			req.ResponsePort.Post(new ResolveResponse { RequestID = req.ID, Status = statusToResolve });
		}

		[Test]
		public void ProcessRequestExistingWorker()
		{
			//Test request for existing worker
			ProcessRequest(true);
		}

		[Test]
		public void ProcessRequestNotExistingWorker()
		{
			//Test request for not existing worker
			ProcessRequest(false);
		}

		private void ProcessRequest(bool existingWorker)
		{
			//expectations on mocks
			workerRegistryMock.Exists(testWorkerType, testWorkerName, true, true);
			LastCall.Return<bool>(existingWorker);
			if (existingWorker)
			{
				Expect.Call(workerRegistryMock.Resolve(testWorkerType, testWorkerName, true)).Return(testWorker);
				Expect.Call(securityServiceMock.Authenticate(null, null))
					.Return(new XcoAuthenticationResult { IsAuthenticated = true, SessionID = testSession });
				Expect.Call(securityServiceMock.Authorize(null, testSession, testWorker)).Return(true);
			}

			//run test
			mocks.ReplayAll();
			resolveWorker = new ResolveWorker(workerRegistryMock, securityServiceMock, messagingPortMock, dpq);
			Port<ResolveResponse> responsePort = new Port<ResolveResponse>();
			ResolveRequest req = new ResolveRequest { ResponsePort = responsePort, WorkerAddress = spaceaddress, WorkerName = testWorkerName, WorkerType = testWorkerType };
			resolveWorker.Post(req);
			Thread.Sleep(100); //wait for response to be posted to response port
			ResolveResponse response = null;
			Assert.IsTrue(responsePort.Test(out response));
			Assert.AreEqual(req.ID, response.RequestID);
			Assert.AreEqual((existingWorker ? ResolveStatus.Ok : ResolveStatus.WorkerNotFound), response.Status);
		}
	}*/
}
